#pragma once

// #include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

// 协议
// Request      请求
// Response     回应
// Serialize    序列化
// Deserialize   反序列化

namespace ns_protocol
{

// #define Myself 1
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

#define SEP "\r\n"
#define SEP_LEN strlen(SEP)

static const char* glerror[] = {
    "success",
    "输入格式错误",
    "除0错误",
    "求余0错误",
    "未定义符号"
};

    class Request
    {
    public:
        Request() {}
        Request(int x, int y, char op) : _x(x), _y(y), _op(op)
        {
        }

        // 转化为序列化字符串
        std::string Serialize()
        {
#ifdef Myself
            std::string str;
            str += std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);
            return str;
#else
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            Json::FastWriter write;
            return write.write(root);
#endif
        }
        // 1 + 2
        bool Deserialize(const std::string &str)
        {
#ifdef Myself
            size_t left = str.find(SPACE);
            size_t right = str.find(SPACE, left + SPACE_LEN);
            size_t end = str.find(SPACE, right + SPACE_LEN);
            if(left == std::string::npos || right == std::string::npos) // 保证两个空格
                return false;
            if(end != std::string::npos)// 保证只有两个空格
                return false;
            if(left == 0 || right + SPACE_LEN == str.size()) // left不在第一个位置，right不在最后一个位置
                return false;
            if(right - left - SPACE_LEN != 1) // 保证左右中间的是一个字符
                return false;
            _x = atoi(str.substr(0, left).c_str());
            _y = atoi(str.substr(right + SPACE_LEN).c_str());
            _op = str[left + SPACE_LEN];
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
            return true;
#endif
        }

    public:
        int _x;
        int _y;
        char _op;
    };

    class Response
    {
    public:
        Response() {}
        Response(int result, int status, int x, int y, char op) 
            : _result(result), _status(status), _x(x), _y(y), _op(op)
        {
        }

        // 转化为序列化字符串
        std::string Serialize()
        {
#ifdef Myself
            std::string str;
            str += std::to_string(_result);
            str += SPACE;
            str += std::to_string(_status);
            return str;
#else
            Json::Value root;
            Json::FastWriter write;
            root["result"] = _result;
            root["status"] = _status;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            return write.write(root);
#endif
        }
        // 11
        bool Deserialize(const std::string &str)
        {
#ifdef Myself
            size_t space = str.find(SPACE);
            size_t end = str.find(SPACE, space + SPACE_LEN);
            if(space == std::string::npos || space == 0 || end != std::string::npos)
                return false;
            _result = atoi(str.substr(0, space).c_str());
            _status = atoi(str.substr(space + SPACE_LEN).c_str());
            return true;
#else
            Json::Value root;
            Json::Reader read;
            read.parse(str, root);
            _result = root["result"].asInt();
            _status = root["status"].asInt();
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
            return true;
#endif
        }

        std::string error()
        {
            return glerror[_status];
        }

    public:
        int _result;
        int _status;

        int _x;
        int _y;
        char _op;
    };

    // 剪去报头 length\r\n*******\r\nlength\r
    std::string Decode(std::string& str)
    {
        // 判断条件是否满足，不满足返回空串
        size_t pos = str.find(SEP);
        if(pos == std::string::npos)
            return "";
        size_t lenght = atoi(str.substr(0, pos).c_str());

        if(lenght > str.size() - pos - SEP_LEN * 2)
            return "";

        str.erase(0, pos + SEP_LEN);
        std::string ret = str.substr(0, lenght);
        str.erase(0, lenght + SEP_LEN);
        return ret;
    }
    
    // 添加报头
    std::string Encode(const std::string& str)
    {
        std::string ret = std::to_string(str.size());
        ret += SEP;
        ret += str;
        ret += SEP;
        return ret;
    }
}
